package com.kugou.miniapp.utils;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.kugou.miniapp.domain.Users;
import com.kugou.miniapp.service.MusicService;
import com.kugou.miniapp.service.UserService;
import lombok.Data;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author：JCccc
 * @Description：
 * @Date： created in 15:56 2019/5/13
 */

@Component
@ServerEndpoint(value = "/match/{userId}")
public class MatchSocket {

//    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @JsonIgnore
    public static Map<String, Map<String, MatchSocket>> build = new ConcurrentHashMap<>();
    //用于保存socket的集合容器
    @JsonIgnore
    public static CopyOnWriteArrayList<MatchSocket> socket_list = new CopyOnWriteArrayList<MatchSocket>();
    //会话
    @JsonIgnore
    public Session session;

    public String getUser_id() {
        return user_id;
    }

    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public String getNick_name() {
        return nick_name;
    }

    public void setNick_name(String nick_name) {
        this.nick_name = nick_name;
    }

    public String getRoom_id() {
        return room_id;
    }

    public void setRoom_id(String room_id) {
        this.room_id = room_id;
    }

    public int getAck() {
        return ack;
    }

    public void setAck(int ack) {
        this.ack = ack;
    }

    //用户的id
    public String user_id;

    public boolean isIs_chat() {
        return is_chat;
    }

    public void setIs_chat(boolean is_chat) {
        this.is_chat = is_chat;
    }

    //是否匹配到正在聊天
    private boolean is_chat = false;

    private String avatar;

    private String nick_name;

    public String room_id = "0";

    public int ack = 0;

    public static MusicService musicService;

    @OnOpen
    public void onOpen(@PathParam("userId") String userId, Session session) throws Exception {
        synchronized (MatchSocket.class){
            userId = userId.substring(0, 20);
            //        logger.info("现在来匹配的客户id："+session.getId()+"用户名："+userId);
            System.out.println("match socket :"+userId+" start "+Thread.currentThread().getName());
//            Thread.sleep(3000);
            //做一些初始化工作
            this.user_id = userId;
            this.session = session;
            //通过userid获取music_list
            musicService = (MusicService) SpringBootBeanUtil.getBean(MusicService.class);
            UserService userService = (UserService)SpringBootBeanUtil.getBean(UserService.class);
            //通过userid设置avatar和nick_name
            Users u = userService.getUserByUserId(userId);
            if(u == null){
                throw new Exception("不存在该用户："+userId);
            }
            this.avatar = u.getAvatar();
            this.nick_name = u.getNick_name();

            //如果已经在socket_list存在userid，那么直接close掉并return
            for (int i = 0; i < socket_list.size(); i++) {
                if (socket_list.get(i).user_id.equals(userId)){
//                logger.info(userId+"：重复连接");
                    try {
                        this.session.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return;
                }
            }
            //把自己的信息加入到map当中去
            socket_list.add(this);
//        logger.info("有连接打开！ 当前在线人数" + socket_list.size());
            //开始匹配其他socket用户
//        logger.info("开始匹配");
            match(socket_list);
            System.out.println("match socket :"+userId+" end "+Thread.currentThread().getName());
        }//synchronized end
    }//onOpen end


    //匹配
    public void match(List<MatchSocket> matchSockets){
        //正在匹配的人数太少，即一个， 则不进行匹配操作
        if (matchSockets.size()<2){
//            logger.info("人数太少， 不进行匹配");
            return;
        }
        for (int i = 0; i < matchSockets.size(); i++) {
            MatchSocket socket = matchSockets.get(i);
            if (socket != this && !socket.is_chat){//不匹配自身或者正在聊天的
                this.setIs_chat(true);
                socket.setIs_chat(true);
                Map<String, MatchSocket> room = new HashMap<>();
                String room_id = UUID.randomUUID().toString();
                this.room_id = room_id;
                socket.room_id = room_id;
                room.put(this.user_id, this);
                room.put(socket.user_id, socket);
                build.put(room_id, room);

                //向已经匹配到的socket发送房间id
                Map<String, String> msg = new HashMap<>();
                msg.put("type", "match");
                msg.put("room_id", room_id);
                String send_msg = JSONObject.fromMap(msg).toString();
                this.session.getAsyncRemote().sendText(send_msg);
                socket.session.getAsyncRemote().sendText(send_msg);
            }
        }
        //匹配失败， 不做任何处理
    }//match end


    @OnError
    public void onError(Session session, Throwable error) {
//        logger.info("服务端发生了错误"+error.getMessage());
        System.out.println("match socket 发生 error:"+error.getMessage());
        //error.printStackTrace();
    }
    /**
     * 连接关闭
     */
    @OnClose
    public void onClose() throws IOException {
        synchronized (MatchSocket.class){
            System.out.println("match socket 发生 close");
            if (this.is_chat&&build.containsKey(this.room_id)){//如果是在聊天室的话
                //获得room
                Map<String, MatchSocket> room = build.get(this.room_id);
                if (room != null){
                    //将socket_list中的socket移除掉
                    for (String uid: room.keySet()){
                        socket_list.remove(room.get(uid));
                        //关闭socket中的session，
                        room.get(uid).session.close();
                    }
                    //将room从build中移除
                    build.remove(this.room_id);
                }
            }else {//不在聊天室, 正在匹配
                if (socket_list.contains(this))
                    socket_list.remove(this);
            }
            //logger.info("有连接关闭！ 当前在线人数" + onlineNumber);
//        logger.info("有连接关闭！ 当前在正在匹配和聊天人数" + socket_list.size());
        }
    }//onClose end

    /**
     * 收到客户端的消息
     *
     * @param message 消息
     * @param session 会话
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("match socket 发生 onMessage");
        try {
//            logger.info("监听到发送来的信息："+message);
            JSONObject jsonObject = JSONObject.fromString(message);
            //获取build中的房间,并设置要返回的聊天信息obj
            Map<String, MatchSocket> room = build.get(jsonObject.getString("room_id"));
            String from_user_id = this.user_id;
            String to_user_id = null;
            for (String u_id: room.keySet()){
                if (!u_id.equals(from_user_id)){
                    to_user_id = u_id;
                }
            }
            String msg = jsonObject.getString("msg");
            //将msg进行包装, from_user_id, to_user_id, type(chat),
            Map<String, String> send_msg = new HashMap<>();
            send_msg.put("msg", msg);
            send_msg.put("type", "chat");
            send_msg.put("from_user_id", from_user_id);
            send_msg.put("to_user_id", to_user_id);
            //时间封装
            Date date = new Date();
            SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
            send_msg.put("time", format.format(date));

            //发送通知信息给两个socket
            String s = JSONObject.fromMap(send_msg).toString();
            room.get(from_user_id).session.getAsyncRemote().sendText(s);
            room.get(to_user_id).session.getAsyncRemote().sendText(s);
        }
        catch (Exception e){

            e.printStackTrace();
//            logger.info("发生了错误了");
        }

    }//onMessage end


    public void sendMessageTo(String message, String TouserId) throws IOException {
    }

    public void sendMessageAll(String message,String FromuserId) throws IOException {
    }


}
